# 1.	数据加载与预处理：
# 系统首先使用sklearn.datasets库加载波士顿房价数据集，该数据集包含了波士顿郊区房屋的中位数价格以及与之相关的13个特征。
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
import torch
(data,target) = load_boston(return_X_y=True)
# 为了消除不同特征之间的量纲差异，系统使用MinMaxScaler进行数据的标准化处理。
from sklearn.preprocessing import MinMaxScaler
data = MinMaxScaler().fit_transform(data)
target = MinMaxScaler().fit_transform(target.reshape(-1,1))
# 接着，系统定义了时间窗口大小（c=7），将数据集转换为RNN模型所需的格式。具体来说，对于每个时间点，系统考虑前c个时间步的特征数据作为输入，并预测接下来一个时间步的房价。
c = 7
x = []
y = []
for i in range(len(data) - c):
    x.append(data[i:i+c])
    y.append(target[i+c])
x = torch.Tensor(x)
y = torch.Tensor(y).reshape(-1,1)
# 2.	模型构建：
# 系统构建了一个基于PyTorch的RNN模型。该模型包括一个RNN层和一个全连接层。RNN层用于捕捉时间窗口内特征的变化信息，而全连接层则用于输出房价的预测值。
class RNN(torch.nn.Module):
    def __init__(self) -> None:
        super().__init__()
        self.rnn1 = torch.nn.RNN(input_size=x.shape[2],hidden_size=5,batch_first=True)
        self.rnn2 = torch.nn.RNN(input_size=5,hidden_size=10,batch_first=True)
        self.fc = torch.nn.Linear(in_features=10,out_features=1)
    def forward(self,x):
        x,_ = self.rnn1(x)
        x,_ = self.rnn2(x)
        out = self.fc(x[:,-1,:])
        return out
# 3.	模型训练：
# 系统将数据集划分为训练集和测试集，但不进行随机打乱以保持数据的时序性。
from sklearn.model_selection import train_test_split
train_x,test_x,train_y,test_y = train_test_split(x,y)
# 使用均方误差（MSE）作为损失函数，并通过Adam优化器进行模型的训练。在训练过程中，系统记录了每次迭代的损失值，以便后续分析。
loss_list = []
model = RNN()
loss_fn = torch.nn.MSELoss()
op = torch.optim.Adam(params=model.parameters(),lr=0.01)
for i in range(1000):
    op.zero_grad()
    h = model(train_x)
    loss = loss_fn(h,train_y)
    loss.backward()
    loss_list.append(loss)
    op.step()
    print(loss)
# 4.	预测与评估：
# 训练完成后，系统使用训练好的模型对测试集进行房价预测。
# 为了评估模型的性能，系统将预测结果与测试集的真实值进行对比，并绘制了预测值与真实值的对比图。
pred = model(test_x).reshape(-1,1)
print(pred)
# 5.	可视化：
# 系统使用matplotlib.pyplot库进行结果的可视化。通过绘制预测值和真实值的对比图，用户可以直观地了解模型的预测效果
plt.plot(test_y.data.numpy(),c='r')
plt.plot(pred.data.numpy(),c='g')
plt.show()